package graphql

import (
	"context"
	"time"

	"github.com/graph-gophers/graphql-go"
	qlclient "github.com/hasura/go-graphql-client"
)

var skywalkingUIAddr string

var DefaultClient qlclient.Client

func SetupSkywalkingUIAddr(addr string) {
	skywalkingUIAddr = addr
	DefaultClient = *qlclient.NewClient(addr, nil)
}

type Span struct {
	ServiceCode  string
	StartTime    int64
	EndTime      int64
	EndpointName string
}

// step为 MINUTE
type Duration struct {
	Start string `json:"start"`
	End   string `json:"end"`
	Step  string `json:"step"`
}

// scope为 Endpoint
type Entity struct {
	Scope        string `json:"scope"`
	ServiceName  string `json:"serviceName"`
	EndpointName string `json:"endpointName"`
	Normal       bool   `json:"normal"`
}

type MetricsCondition struct {
	Name   string `json:"name"`
	Entity Entity `json:"entity"`
}

type KVInt struct {
	Id    graphql.ID
	Value int64
}

type IntValues struct {
	Values []KVInt
}

type MetricsValues struct {
	Label  string
	Values IntValues
}

type ReadLabeledMetricsValues struct {
	Label  string
	Values MetricsValues
}

var layout = "2006-01-02 150405"
var swLayout = "2006-01-02 1504"

func GetCondition(serviceName string, endpointName string, start string, end string, metricName string) (MetricsCondition, Duration) {
	var condition = MetricsCondition{
		Name: metricName,
		Entity: Entity{
			Scope:        "Endpoint",
			ServiceName:  serviceName,
			EndpointName: endpointName,
			Normal:       true,
		},
	}

	startDate, _ := time.Parse(layout, start)
	endDate, _ := time.Parse(layout, end)

	var duration = Duration{
		Start: startDate.Format(swLayout),
		End:   endDate.Format(swLayout),
		Step:  "MINUTE",
	}
	return condition, duration
}

// 查询该endpoint的duration内每分钟平均响应时间
func GetTimeseriesMetric(condition MetricsCondition, duration Duration) (map[int64]any, error) {
	variable := map[string]interface{}{
		"condition": condition,
		"duration":  duration,
	}

	var query struct {
		ReadMetricsValues struct {
			MetricsValues
		} `graphql:"readMetricsValues(duration: $duration, condition: $condition)"`
	}

	err := DefaultClient.Query(context.Background(), &query, variable)
	if err != nil {
		return nil, err
	}

	length := len(query.ReadMetricsValues.MetricsValues.Values.Values)
	// result := make([]int64, length)
	startTime, _ := time.Parse(swLayout, duration.Start)

	//将开始时间转化为int64类型的时间戳格式
	startUnix := startTime.UnixMilli() //开始时间，s级别
	// startUnix := startUnix_s * 1000 //时间戳扩大为和v.Timestamp同等的比例。ms级别

	var result map[int64]any = make(map[int64]any)

	for i := 0; i < length; i++ {
		// query.ReadMetricsValues.MetricsValues.
		result[startUnix] = query.ReadMetricsValues.MetricsValues.Values.Values[i].Value
		startUnix += 60000
	}
	return result, nil
}

func GetLabeldTimeseriesMetric(condition MetricsCondition, duration Duration, label []string) (map[string]map[int64]any, error) {
	variable := map[string]interface{}{
		"condition": condition,
		"duration":  duration,
		"labels":    label,
	}

	var query struct {
		ReadLabeledMetricsValues []struct {
			MetricsValues
		} `graphql:"readLabeledMetricsValues(duration: $duration, condition: $condition, labels: $labels)"`
	}

	err := DefaultClient.Query(context.Background(), &query, variable)
	if err != nil {
		return nil, err
	}

	var result map[string]map[int64]any = make(map[string]map[int64]any)

	for _, metricValues := range query.ReadLabeledMetricsValues {
		var timeSeries map[int64]any = make(map[int64]any)
		length := len(metricValues.Values.Values)
		// result := make([]int64, length)
		startTime, _ := time.Parse(swLayout, duration.Start)

		//将开始时间转化为int64类型的时间戳格式
		startUnix := startTime.UnixMilli() //开始时间，s级别
		// startUnix := startUnix_s * 1000 //时间戳扩大为和v.Timestamp同等的比例。ms级别

		for i := 0; i < length; i++ {
			timeSeries[startUnix] = metricValues.Values.Values[i].Value * 1e6
			startUnix += 60000
		}

		result[metricValues.Label] = timeSeries
	}

	return result, nil
}
